/***************************************************************************
 * This code and information is provided "as is" without warranty of any   *
 * kind, either expressed or implied, including but not limited to the     *
 * implied warranties of merchantability and/or fitness for a particular   *
 * purpose.                                                                *
 *                                                                         *
 * Copyright (C) 2008 Teridian SemiConductor, Corp. All Rights Reserved.   *
 *                                                                         *
 ***************************************************************************/
//**************************************************************************//
//                                                                          // 
//  DESCRIPTION: TSCP-CCID                                                  //
//               HexStringDecoder.cs                                        //
//  HexStringDecoder is an object that analyze a string of hex numbers      //
//  and split them into array of bytes or characters, vice and versa...     //
//  The input of this object is either a string or a byte array             //
//                                                                          //
//  AUTHOR:  SD                                                             //
//                                                                          //
//  HISTORY: 2007 SEPTEMBER 26; First Version Released 1.0                  //
//           2007 DECMBER   14; Version 2.00 Release                        //
//                                                                          //
//**************************************************************************//
/***************************************************************************
 * This code was adapted from HexStringDecoder.cs which was originally     *
 * written by Teridian SemiConductor, Corp. It has been modified from its  *
 * original version to allow for use in the .NET Micro Framework.          *
 * Unneccessary functions have been removed, as well as the addition of    *
 * the Dec2Hex function.                                                   *
 * LAST MODIFIED: 2010 April 23                                            *
 * Copyright (C) 2009 Gemalto                                              *
 ***************************************************************************/
/***************************************************************************
 *  HexStringDecoder.cs is part of the PC/SC Micro API for the .NET        *
 *  Micro Framework.                                                       *
 *                                                                         *
 *  The PC/SC Micro API for the .NET Micro Framework is free software:     *
 *  you can redistribute it and/or modify it under the terms of the GNU    *
 *  General Public License as published by the Free Software Foundation,   *
 *  either version 2 of the License, or (at your option) any later version.*
 *                                                                         *
 *  The PC/SC Micro API for the .NET Micro Framework is distributed in     *
 *  the hope that it will be useful, but WITHOUT ANY WARRANTY; without even*
 *  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR    *
 *  PURPOSE.  See the GNU General Public License for more details.         *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with the PC/SC Micro API for the .NET Micro Framework. If not,   *
 *  see <http://www.gnu.org/licenses/>.                                    *
 ***************************************************************************/
using System;
using System.Text;
using Microsoft.SPOT;

namespace PCSCMicro
{
    /// <summary>
    /// This class does conversions for the API
    /// </summary>
    /// <remarks>
    /// Most of the conversions involve hexidecimal notation strings
    /// or bytes, however there is a conversion from a uint to a byte
    /// array also which is used by BigInteger.
    /// </remarks>
    public static class HexStringDecoder
    {
        const string hex = "0123456789ABCDEF";

        /// <summary>
        /// Converts a byte to hex string of length 2.
        /// </summary>
        /// <example>
        /// b = 204 = 0xCC, is decoded into "CC".
        /// </example>
        /// <remarks>
        /// Used for values from 0 to 0xFF = 255.
        /// </remarks>
        /// <param name="b">Value to be converted to hex</param>
        /// <returns>Hex string representation of b</returns>
        public static string ByteToHex(byte b)
        {
            int lowNibble = b & 0x0F;
            int highNibble = (b & 0xF0) >> 4;
            string s = new string(new char[] { hex[highNibble], hex[lowNibble] });
            return s;
        }
        
        /// <summary>
        /// Converts hex string of length 2 to int.
        /// </summary>
        /// <remarks>
        /// Used for values from 0 to 0xFF = 255.
        /// </remarks>
        /// <example>
        /// hexStr = "CC" is decoded into int 204 = 0xCC.
        /// </example>
        /// <param name="HexStr">Hex string to be converted to decimal.</param>
        /// <returns>Decimal representation of hexStr</returns>
        public static int HexStringToInt(string HexStr)
        {
            int hi, lo;
            if (HexStr.Length != 2)
            {
                return -1;
            }
            hi = Hex2Dec(HexStr[0]);
            lo = Hex2Dec(HexStr[1]);
            return ((hi << 4) + (lo));
        }
        
        /// <summary>
        /// Converts hex string of any length to a Byte array
        /// with same hex representation.
        /// </summary>
        /// <example>
        /// HexStr = C0AAC0C0CC80..., is decoded into 
        /// byte array [ 0xC0, 0xAA, 0xC0, 0xC0, 0xCC, 0x80, ...].
        /// </example>
        /// <param name="HexStr">Hex string to be converted to decimal
        /// byte array</param>
        /// <returns>Decimal byte array representing HexStr</returns>
        public static byte[] StringToByteArray(string HexStr)
        {
            if (HexStr.Length % 2 == 1)
                HexStr += "0";
            byte[] bArr = new byte[HexStr.Length / 2];
            int Hi, Lo;
            int bytecount = HexStr.Length / 2;;
            for (int i = 0; i < (HexStr.Length / 2); i++)
            {
                Hi = Hex2Dec(HexStr[i * 2]);
                Lo = Hex2Dec(HexStr[i * 2 + 1]);
                bArr[i] = (byte)((Hi << 4) + (Lo));
            }
            return bArr;
        }
        
        /// <summary>
        /// Converts a uint number to equivalent hex value.
        /// </summary>
        /// <remarks>
        /// Used for values of up to 4294967295 = 0xFFFFFFFF.
        /// </remarks>
        /// <example>
        /// x = 4275878401 = 0xFEDCBA01 is decoded to "FEDCBA01".
        /// </example>
        /// <param name="x">Decimal value to convert to hex string</param>
        /// <returns>Hex string representing x</returns>
        public static string Dec2Hex(uint x)
        {
            char[] ret = new char[8];
            for (int i = 7; i >= 0; i--)
            {
                ret[i] = hex[(int)(x & 0x0F)];
                x >>= 4;
            }
            return new string(ret);
        }

        /// <summary>
        /// Converts a uint number to equivalent byte array.
        /// </summary>
        /// <remarks>
        /// Used for values of up to 4294967295 = 0xFFFFFFFF.
        /// </remarks>
        /// <example>
        /// x = 4275878401 = 0xFEDCBA01 is decoded to [0xFE, 0xDC, 0xBA, 0x01].
        /// </example>
        /// <param name="x">uint to convert to ByteArray</param>
        /// <returns>Byte array of length 4 which when concatenated together
        /// has the same value as x</returns>
        public static byte[] uintToByteArray(uint x)
        {
            byte[] ret = new byte[4];
            for (int i = 3; i >= 0; i--)
            {
                ret[i] = (byte)(x & 0xFF);
                x >>= 8;
            }
            return ret;
        }

        /// <summary>
        /// Converts a byte array to equivalent hex string.
        /// </summary>
        /// <example>
        /// ByteArray =  [ 0xC0, 0xAA, 0xC0, 0xC0, 0xCC, 0x80]
        /// and bytecount = 6 is decoded to HexStr = "C0AAC0C0CC80".
        /// </example>
        /// <param name="ByteArray">Decimal byte array to be 
        /// converted to a hex string</param>
        /// <param name="bytecount">Number of bytes from the array
        /// to be converted</param>
        /// <returns>Hex string representation of the first bytecount
        /// cells in ByteArray</returns>
        public static string ByteArrayToString(byte[] ByteArray, int bytecount)
        {
            string HexStr = null;
            for (int i = 0; i < bytecount; i++)
                HexStr += ByteToHex(ByteArray[i]);
            return HexStr;
        }

        // Helper function for this class
        // Convert a char into hex value.
        // For example, 'A' is 0xA or 10, 'C' is 0xC or 12
        static int Hex2Dec(char c)
        {
            if ((c >= '0') && (c <= '9'))
            {
                return (c - '0');
            }
            else if ((c >= 'A') && (c <= 'F'))
            {
                return (c - 'A' + 10);
            }
            return 0;
        }
    }
}
